home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / LIB / MENU.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  15.1 KB  |  475 lines

  1. package sub_arctic.lib;
  2. import sub_arctic.input.*;
  3. import sub_arctic.lib.sub_arctic_error;
  4. import sub_arctic.constraints.constraint;
  5. import sub_arctic.output.style;
  6. import sub_arctic.output.style_manager;
  7. import sub_arctic.output.drawable;
  8. import java.awt.Font;
  9.  
  10. /**
  11.  * This class implements a columnar menu. It expects to popped up 
  12.  * and down based on input from the menu_focus_agent. This object
  13.  * also holds the reference to the menu_focus_agent in a static
  14.  * variable. <p>
  15.  * 
  16.  * You can put any interactor in this object as a child, but only
  17.  * things which are subclasses of menu_item will get the highlight
  18.  * behavior and get notified when they are selected. Thus it is 
  19.  * useful to put labels or spacers in this object to decorate your
  20.  * menu.
  21.  * 
  22.  * @author Ian Smith 
  23.  */
  24. public class menu extends column implements menu_focusable  {
  25.  
  26.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  27.  
  28.   /**
  29.    * Construct a menu. This version assumes you want to use the style
  30.    * system's beveling routines to figure out your spacing.
  31.    * @param int xv x position of this interactor
  32.    * @param int yv y position of this interactor
  33.    */
  34.   public menu(int x, int y) 
  35. {
  36.     // XXX assumes that the beveling of the style is symmetrical
  37.     // XXX in X and Y
  38.     super(style_manager.current_style().drawable_horizontal_space(),
  39.       0,false,false,column.LEFT_JUSTIFIED);
  40.     set_x(x);
  41.     set_y(y);
  42.     set_selected_item(-1);
  43.     set_visible(false);
  44.   }
  45.  
  46.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  47.  
  48.   /**
  49.    * Construct a menu. This version assumes you want to use the style
  50.    * system's beveling routines to figure out your spacing.
  51.    * @param int             xv x position of this interactor
  52.    * @param int             yv y position of this interactor
  53.    * @param callback_object co the object to send callbacks to
  54.    */
  55.   public menu(int x, int y, callback_object co) 
  56. {
  57.     // XXX assumes that the beveling of the style is symmetrical
  58.     // XXX in X and Y
  59.     super(style_manager.current_style().drawable_horizontal_space(),
  60.       0,false,false,column.LEFT_JUSTIFIED);
  61.     _callback_obj=co;
  62.     set_x(x);
  63.     set_y(y);
  64.     set_selected_item(-1);
  65.     set_visible(false);
  66.   }
  67.  
  68.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  69.  
  70.   /**
  71.    * Construct a menu. This version assumes you want to use the style
  72.    * system's beveling routines to figure out your spacing and 
  73.    * the constraint system to do your placement.
  74.    *
  75.    * @param callback_object co the object to send callbacks to
  76.    */
  77.   public menu(callback_object co) 
  78. {
  79.     // XXX assumes that the beveling of the style is symmetrical
  80.     // XXX in X and Y
  81.     super(style_manager.current_style().drawable_horizontal_space(),
  82.       0,false,false,column.LEFT_JUSTIFIED);
  83.     _callback_obj=co;
  84.     set_selected_item(-1);
  85.     set_visible(false);
  86.   }
  87.  
  88.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  89.  
  90.   /**
  91.    * Construct a menu. This version assumes you want to use the style
  92.    * system's beveling routines to figure out your spacing and 
  93.    * the constraint system to do your placement.
  94.    *
  95.    */
  96.   public menu() 
  97. {
  98.     // XXX assumes that the beveling of the style is symmetrical
  99.     // XXX in X and Y
  100.     super(style_manager.current_style().drawable_horizontal_space(),
  101.       0,false,false,column.LEFT_JUSTIFIED);
  102.     set_selected_item(-1);
  103.     set_visible(false);
  104.   }
  105.  
  106.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  107.  
  108.   /**
  109.    * This holds the callback object.
  110.    */
  111.   callback_object _callback_obj=null;
  112.  
  113.   /**
  114.    * Get the value of the current callback object.
  115.    * @return callback_object the current object who gets the callbacks of this 
  116.    *                         menu.
  117.    */
  118.   callback_object callback_obj() { return _callback_obj;};
  119.  
  120.   /**
  121.    * Change the value of the current callback object.
  122.    * @param callback_object c the new callback object.
  123.    */
  124.   void set_callback_obj(callback_object c) { _callback_obj=c;};
  125.  
  126.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  127.  
  128.   /**
  129.    * This function gets called during the process of the user
  130.    * dragging around on the menu. The menu should probably
  131.    * use pick() to figure out who to highlight based on this
  132.    * event. We ignore the user_info for now.
  133.    *  
  134.    * @param event  evt       the event causing the feedback.
  135.    * @param Object user_info (not used) this is the object we passed to the 
  136.    *                         menu_focus_agent when we made ourselves the focus.
  137.    */
  138.   public void menu_feedback(event evt,Object user_info ) {
  139.     pick_collector pc=new pick_collector();
  140.     int i,index;
  141.     user_info_holder uih;
  142.     menu_item mi;
  143.  
  144.     /* run a pick on the location */
  145.     pick(evt.local_x(), evt.local_y(), pc);
  146.     
  147.     /* loop over everything picked */
  148.     for (i=0;i<pc.num_picks(); ++i) {
  149.       
  150.       /* grab the ith and see if its a menu item */
  151.       uih=pc.pick(i);
  152.       if (uih.obj instanceof menu_item) {
  153.     index=find_child(uih.obj);
  154.  
  155.     /* if the index is -1, there might be one of our children
  156.        later on... in particular, the -1 child might be a child
  157.        of one of our children */
  158.     if (index==-1) continue;
  159.  
  160.     /* if its already selected don't bother */
  161.     if (index==selected_item()) return;
  162.  
  163.     /* if somebody else needs to be unhighlighted, unless nobody 
  164.        is selected */
  165.     if (selected_item()!=-1) {
  166.       mi=(menu_item)child(selected_item());
  167.       mi.unhighlight(evt);
  168.     } 
  169.     
  170.     /* tell this guy he's selected */
  171.     mi=(menu_item)child(index);
  172.     mi.highlight(evt);
  173.     set_selected_item(index);
  174.       }
  175.     }
  176.   }
  177.  
  178. /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  179.   
  180.   /** Callback constant number for menu selection callback */
  181.   public static final int MENU_SELECT_CALLBACK = 0;
  182.   
  183. /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  184.  
  185.   /**
  186.    * This function gets called to inform you that the mouse button
  187.    * was released over your menu. Again, no use of user_info for now.
  188.    * 
  189.    * @param event  evt       the event which terminated the interactor 
  190.    *                         (probably a mouse up).
  191.    * @param Object user_info (not used) the object we passed to the 
  192.    *                         menu_focus_agent when we put ourselves into the 
  193.    *                         menu focus.
  194.    */
  195. public void menu_release(event evt, Object user_info) {
  196.   int i,index;
  197.   user_info_holder uih;
  198.   pick_collector pc=new pick_collector();
  199.  
  200.   /* run a pick on the location */
  201.   pick(evt.local_x(), evt.local_y(), pc);
  202.   
  203.   /* loop over everything picked */
  204.   for (i=0;i<pc.num_picks(); ++i) {
  205.     
  206.     /* grab the ith and see if its a menu item */
  207.     uih=pc.pick(i);
  208.     if (uih.obj instanceof menu_item) {
  209.       index=find_child(uih.obj);
  210.       
  211.       /* is it not one of our children? */
  212.       if (index==-1) return;
  213.       
  214.       /* got the winner ... look for a callback object */
  215.       if (callback_obj()!=null) {
  216.     callback_obj().callback(this,evt,MENU_SELECT_CALLBACK,child(index));
  217.     
  218.       }
  219.     }
  220.   }
  221. }
  222.  
  223. /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  224.  
  225.   /**
  226.    * This function gets called to inform you that you have been put into
  227.    * the focus set (in this case the menu_focus_agent is the agent 
  228.    * whose set you are in). We pop up (display) the menu at this point.
  229.    * 
  230.    * @param event cause_event the event that caused you to enter the focus set
  231.    * @param focus_dispatch_agent of_agent  this is the agent whose set you have 
  232.    *                                       been added to (we ignore this right 
  233.    *                                       now).
  234.    * @param Object               user_info the object you passed to the agent 
  235.    *                                       when you asked to enter the set (we 
  236.    *                                       ignore this right now).
  237.    */
  238. public void focus_set_enter(event cause_evt,
  239.                 focus_dispatch_agent of_agent /* ignored */,
  240.                 Object user_info /* ignored */) {
  241.   menu_item mi;
  242.   /* initially there is nobody selected */
  243.   if (selected_item()!=-1) {
  244.     mi=(menu_item)child(selected_item());
  245.     mi.unhighlight(cause_evt);
  246.   }
  247.   set_selected_item(-1);
  248.   set_visible(true);
  249. }
  250.   
  251.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  252.  
  253.   /**
  254.    * This is called when the menu leaves the focus set. We use it
  255.    * pop-down (remove from the display) the menu. We do this because
  256.    * we know that the "active" menus with respect to the 
  257.    * menu_focus_agent (the one's the user is interacting with) are
  258.    * always kept in the focus set.
  259.    * 
  260.    * @param event                cause_event the event that caused you to exit 
  261.    *                                         the focus set.
  262.    * @param focus_dispatch_agent of_agent    this is the agent whose set you 
  263.    *                                         have just left (we ignore this 
  264.    *                                         right now).
  265.    * @param Object               user_info   the object you passed to the agent 
  266.    *                                         when you asked to enter the set 
  267.    *                                         (we ignore this right now).
  268.    */
  269.   public void focus_set_exit(event cause_evt, 
  270.                  focus_dispatch_agent of_agent /* ignored */,
  271.                  Object user_info /* ignored */){
  272.     menu_item mi;
  273.     set_visible(false);
  274.     
  275.     /* possibly tell people to not be in highlighted state across
  276.        runs */
  277.     if (selected_item()!=-1) {
  278.       
  279.       /* tell him to go off */
  280.       mi=(menu_item)child(selected_item());
  281.       mi.unhighlight(cause_evt);
  282.       set_selected_item(-1);
  283.       
  284.       /* remove us from the parent */
  285.       parent().remove_child(this);
  286.     }
  287.   }
  288.   
  289.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  290.  
  291.   /**
  292.    * Value, get & set functions for the selected item. This is 
  293.    * -1 when nothing is selected.
  294.    */
  295.   protected int _selected_item;
  296.  
  297.   /**
  298.    * Return the currently selected item's number. You will get -1
  299.    * when nothing is selected.
  300.    * 
  301.    * @return int the currently selected item's number
  302.    */
  303.   public int selected_item() { return _selected_item;};
  304.  
  305.   /**
  306.    * Change the currently selected item.
  307.    * @param int v the new selected item (use -1 for no selected item)
  308.    */
  309.   public void set_selected_item(int v) { _selected_item=v;};
  310.   
  311.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  312.  
  313.   /**
  314.    * This holds the menu focus agent which is only used by the
  315.    * menu code.
  316.    */
  317.   static menu_focus_agent _agent;
  318.  
  319.   /**
  320.    * Return the menu_focus_agent.
  321.    * @param menu_focus_agent the system's menu_focus_agent.
  322.    */
  323.   static public menu_focus_agent agent() {return _agent;};
  324.   
  325.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  326.  
  327.   /*
  328.    * static initializer to set up the agent. 
  329.    */
  330.   static {
  331.     _agent=new menu_focus_agent();
  332.     manager.focus_policy.add_agent_after(_agent,null);
  333.   }
  334.   
  335.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  336.  
  337.   /**
  338.    * This gets called to tell us that the pointer has left us. We
  339.    * just reset our state to not having anything selected. 
  340.    * 
  341.    * @param event  evt       the event that caused us to be exited (probably a 
  342.    *                         mouse movement).
  343.    * @param Object user_info the object you passed to the agent when you asked 
  344.    *                         to enter the set (we ignore this right now).
  345.    */
  346.   public void menu_exit(event evt, Object user_info /* ignored */) {
  347.  
  348.     if (selected_item()!=-1) {
  349.       /* we had a selection... send the unhighlight command */
  350.       ((menu_item)child(selected_item())).unhighlight(evt);
  351.       
  352.       /* reset to no selection */
  353.       set_selected_item(-1);
  354.     }
  355.   }
  356.   
  357.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  358.  
  359.   /**
  360.    * This gets called to ask us what child would result from 
  361.    * this point. This is used by the menu_focus_agent to determine
  362.    * if the user is "pointing at" another pullright which would
  363.    * result in a different menu being popped up from the one that
  364.    * is currently popped up. 
  365.    *
  366.    * @param int local_x the x coordinate in question in our coordinate system
  367.    * @param int local_y the y coordinate in question in our coordinate system
  368.    */
  369.   public menu menu_generates_submenu(int local_x, int local_y) {
  370.     int i,index;
  371.     user_info_holder uih;
  372.     pick_collector pc=new pick_collector();
  373.  
  374.     /* run a pick on the location */
  375.     pick(local_x,local_y, pc);
  376.     
  377.     /* loop over everything picked */
  378.     for (i=0;i<pc.num_picks(); ++i) {
  379.  
  380.       /* grab the ith and see if its a menu item */
  381.       uih=pc.pick(i);
  382.       if (uih.obj instanceof pullright_menu_item) {
  383.     
  384.     /* which child is it? */
  385.     index=find_child(uih.obj);
  386.     
  387.     /* is it not one of our children? */
  388.     if (index==-1) continue;
  389.     
  390.     /* return the menu of this item */
  391.     return (((pullright_menu_item)child(index)).pullright());
  392.       }
  393.     }
  394.  
  395.     /* couldn't find a menu */
  396.     return null;
  397.   }
  398.   
  399.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  400.  
  401.   /**
  402.    * This is a special version of draw self local to allow us to
  403.    * give the object a raised look.
  404.    * @param drawable d the surface to draw on.
  405.    */
  406.   public void draw_self_local(drawable d) 
  407.     {
  408.       style cs=style_manager.current_style();
  409.  
  410.       cs.drawable_prepare_rect(d,0,0,w(),h(),true, true);
  411.       draw_children(d);
  412.     }
  413.   
  414.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  415.  
  416.   /**
  417.    * This is a convenience function for creating a simple menu from
  418.    * text strings in some font.
  419.    *
  420.    * @param String[]        value the array of strings to place on the menu
  421.    * @param Font            f     the font to build the menu items in (if you 
  422.    *                              pass null you will get the system default 
  423.    *                              font).
  424.    * @param callback_object co    the object to send the callbacks to 
  425.    * @return menu a menu with a set of text_menu_items in it (one for each 
  426.    *              string)
  427.    */
  428.   static public menu create_text_menu(
  429.                       String[]        value, 
  430.                       Font            f, 
  431.                       callback_object co) 
  432.     {
  433.       Font font;
  434.       menu m=new menu(co);
  435.       int max,i;
  436.  
  437.       /* set the font up */
  438.       if (f==null) {
  439.     font=style_manager.default_font();
  440.       } else {
  441.     font=f;
  442.       }
  443.     
  444.       /* find out the largest one */
  445.       max=text_menu_item.max_item_width(value,font);    
  446.  
  447.       /* loop over the strings */
  448.       for (i=0; i<value.length; ++i) {
  449.     m.add_child(new text_menu_item(value[i],max));
  450.       }
  451.  
  452.       /* we're done */
  453.       return m;
  454.     }
  455.   
  456.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  457.  
  458. }
  459. /*=========================== COPYRIGHT NOTICE ===========================
  460.  
  461. This file is part of the subArctic user interface toolkit.
  462.  
  463. Copyright (c) 1996 Scott Hudson and Ian Smith
  464. All rights reserved.
  465.  
  466. The subArctic system is freely available for most uses under the terms
  467. and conditions described in 
  468.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  469. and appearing in full in the lib/interactor.java source file.
  470.  
  471. The current release and additional information about this software can be 
  472. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  473.  
  474. ========================================================================*/
  475.